package com.yixun.qfbao.api.service.impl;

import com.yixun.qfbao.api.service.CompanyService;
import com.yixun.qfbao.api.service.ResourcesService;
import com.yixun.qfbao.api.service.RoleCaseMemberService;
import com.yixun.qfbao.api.service.RoleResourcesService;
import com.yixun.qfbao.apidto.*;
import com.yixun.qfbao.constant.RedisKeyConstant;
import com.yixun.qfbao.mapper.RoleResourcesMapper;
import com.yixun.qfbao.model.ZNodes;
import com.yixun.qfbao.model.*;
import com.yixun.qfbao.model.dto.RoleResourcesDto;
import com.yixun.qfbao.model.dto.UserResourcesDto;
import com.yixun.qfbao.model.enums.ResourcesOriginEnum;
import com.yixun.qfbao.model.enums.ResourcesTypeEnum;
import com.yixun.qfbao.model.enums.SystemIdEnum;
import com.yixun.qfbao.service.PartnerInfoService;
import com.yixun.qfbao.util.RedisUtil;
import com.yixun.qfbao.xf.model.enums.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author guifang.weng
 * @create 2017-11-23 11:39
 **/
@Slf4j
@Service
public class RoleResourcesServiceImpl implements RoleResourcesService {

    @Autowired
    private RoleResourcesMapper roleResourcesMapper;
    @Autowired
    private ResourcesService resourcesService;
    @Autowired
    private PartnerInfoService partnerInfoService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private RoleCaseMemberService roleCaseMemberService;

    @Override
    public GetAuthorizeRoleListResDto getAuthorizeRoleList(GetAuthorizeRoleListReqDto getAuthorizeRoleListReqDto) throws Exception {
        GetAuthorizeRoleListResDto resDto = new GetAuthorizeRoleListResDto();

        // 查询所有功能权限
        UserResourcesDto userResourcesDto = new UserResourcesDto();
        String loginType = getAuthorizeRoleListReqDto.getLoginType();
        String outsideSwitch = "";
        //判断请求来自手机端还是PC端   此处以前的业务逻辑为 ResourcesTypeEnum.PC  写死获取PC端
        if (SystemIdEnum.AGENCY_h5.getCode().equals(loginType) ||SystemIdEnum.WEAPP_AGENCY.getCode().equals(loginType) || SystemIdEnum.ASSISTANT.getCode().equals(loginType)
        	|| SystemIdEnum.APP_ASSISTANT.getCode().equals(loginType) || SystemIdEnum.APP_AGENCY.getCode().equals(loginType)) {
            userResourcesDto.setResourcesType(ResourcesTypeEnum.APP.getNo());
        }else if (SystemIdEnum.AGENCY_WEB.getCode().equals(loginType)) {
            userResourcesDto.setResourcesType(ResourcesTypeEnum.PC.getNo());
        }else if (SystemIdEnum.DEVELOPERS.getCode().equals(loginType)) {
        	//巧渠道,判断公司是否需要外部分销.控制分销流量报表是否展示
        	PartnerInfo pi = partnerInfoService.selectById(Long.valueOf(getAuthorizeRoleListReqDto.getUserId()));
        	if(null != pi) {
        		Company company = companyService.getCompanyById(pi.getHigherid());
        		outsideSwitch = company.getOutsideSwitch();
        	}
        }
        //此处以前的业务逻辑是ResourcesOriginEnum.CHANNEL 写死为分销商
        userResourcesDto.setResourcesOrigin(getAuthorizeRoleListReqDto.getResourcesOrigin());
        List<Resources> responseList = resourcesService.findUserResources(userResourcesDto);

        //查询该角色已被授权的权限
        RoleResourcesDto roleResourcesDto = new RoleResourcesDto();
        roleResourcesDto.setRoleId(getAuthorizeRoleListReqDto.getRoleId());
        List<RoleResources> authorizedList = roleResourcesMapper.selectListByDto(roleResourcesDto);
        //组装Znodes
        List<ZNodes> list = new ArrayList<>();
        if (responseList != null && responseList.size() > 0) {
            for (Resources r : responseList) {
            	//无外部分销,过滤分销流量报表菜单
            	if(("0".equals(outsideSwitch) || "".equals(outsideSwitch)) && SystemIdEnum.DEVELOPERS.getCode().equals(loginType)) {
            		if("menu_0007_0004".equals(r.getResourcesCode())) {
            			//当公司关闭外部分销功能,清除角色分配过的历史分销流量统计菜单
            			roleResourcesDto = new RoleResourcesDto();
            			roleResourcesDto.setRoleId(getAuthorizeRoleListReqDto.getRoleId());
            			roleResourcesDto.setResourcesCode("menu_0007_0004");
            			List<RoleResources> roleResourcesList = roleResourcesMapper.selectListByDto(roleResourcesDto);
            			if(null != roleResourcesList && roleResourcesList.size() == 1) {
            				RoleResources roleResources = roleResourcesList.get(0);
            				roleResourcesMapper.delById(roleResources.getId());
            			}
            			continue;
            		}
            	}
                ZNodes znode = new ZNodes();
                znode.setId(r.getResourcesCode());
                znode.setpId(r.getParentCode());
                znode.setName(r.getResourcesName());
                znode.setChkDisabled("false");
                boolean flag = false;
                if (authorizedList != null && authorizedList.size() > 0) {
                    for (RoleResources rr : authorizedList) {
                        if (r.getResourcesCode().equals(rr.getResourcesCode())) {
                            flag = true;
                            break;
                        }
                    }
                }
                znode.setChecked(String.valueOf(flag));
                list.add(znode);
            }
        }
        resDto.setResult(ResultEnum.SUCCESS.getNo());
        resDto.setNodeList(list);
        return resDto;
    }

    @Override
    public AgencyRoleAuthResourcesResDto getAgencyRoleAuthResources(GetAuthorizeRoleListReqDto getAuthorizeRoleListReqDto) {
        AgencyRoleAuthResourcesResDto resDto = new AgencyRoleAuthResourcesResDto();

        // 获取分销所有权限信息
        UserResourcesDto userResourcesDto = new UserResourcesDto();
        userResourcesDto.setResourcesType(ResourcesTypeEnum.PC.getNo());
        userResourcesDto.setResourcesOrigin(getAuthorizeRoleListReqDto.getResourcesOrigin());
        List<Resources> resourcesList = resourcesService.findUserResources(userResourcesDto);

        //查询该角色已被授权的权限
        RoleResourcesDto roleResourcesDto = new RoleResourcesDto();
        roleResourcesDto.setRoleId(getAuthorizeRoleListReqDto.getRoleId());
        List<RoleResources> authorizedList = roleResourcesMapper.selectListByDto(roleResourcesDto);
        List<String> authorizedCode = authorizedList.stream().map(RoleResources::getResourcesCode)
                .collect(Collectors.toList());

        List<TreeData> treeDataList = new ArrayList<>();
        List<Resources> filterList = resourcesList.stream()
                .filter(item -> item.getParentCode().equals("menu_0000"))
                .collect(Collectors.toList());
        for(Resources resources: filterList){
            TreeData treeData = buildTreeData(resources, resourcesList, null);
            treeDataList.add(treeData);
        }
        resDto.setResult(ResultEnum.SUCCESS.getNo());
        resDto.setCheckedKeys(authorizedCode);
        resDto.setTreeDataList(treeDataList);
        return resDto;
    }

    private TreeData buildTreeData(Resources resources, List<Resources> resourcesList, TreeData treeData){
        if(Objects.isNull(treeData)){
            treeData = new TreeData();
        }
        treeData.setLabel(resources.getResourcesName());
        treeData.setResourcesCode(resources.getResourcesCode());
        List<Resources> childResources = resourcesList.stream()
                .filter(item -> item.getParentCode().equals(resources.getResourcesCode()))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(childResources)){
            List<TreeData> children = new ArrayList<>();
            for(Resources child: childResources){
                TreeData childData = new TreeData();
                childData.setLabel(child.getResourcesName());
                childData.setResourcesCode(child.getResourcesCode());
                children.add(childData);
                buildTreeData(child, resourcesList, childData);
            }
            treeData.setChildren(children);
        }
        return treeData;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AuthorizeRoleResDto authorizeRole(AuthorizeRoleReqDto authorizeRoleReqDto) throws Exception {
        AuthorizeRoleResDto resDto = new AuthorizeRoleResDto();
        String loginType = authorizeRoleReqDto.getLoginType();
        String origin = "";
        //判断请求来自手机端还是PC端   此处以前的业务逻辑为 ResourcesTypeEnum.PC  写死获取PC端
        if (SystemIdEnum.DEVELOPERS.getCode().equals(loginType) || SystemIdEnum.ASSISTANT.getCode().equals(loginType)) {
            origin = ResourcesOriginEnum.DEVELOPERS.getNo();
        }else if (SystemIdEnum.AGENCY_WEB.getCode().equals(loginType) || SystemIdEnum.AGENCY_h5.getCode().equals(loginType)|| SystemIdEnum.WEAPP_AGENCY.getCode().equals(loginType)) {
            origin = ResourcesOriginEnum.CHANNEL.getNo();
        }
        //删除当前角色下的权限
        roleResourcesMapper.delRoleWithType(authorizeRoleReqDto.getRoleId(),origin);
        //保存角色资源
        List<String> resourcesList = authorizeRoleReqDto.getResourcesList();
        if(resourcesList != null && resourcesList.size() > 0) {
            List<RoleResourcesDto> list = new ArrayList<>();
            for (String resourcesStr : resourcesList) {
                if(StringUtils.isBlank(resourcesStr)) continue;
                String[] resourcesCodesArr = resourcesStr.split(",");
                if(resourcesCodesArr.length > 0) {
                    for(String resourcesCode : resourcesCodesArr){
                        if(StringUtils.isNotBlank(resourcesCode)){
                            RoleResourcesDto rrDto = new RoleResourcesDto();
                            rrDto.setRoleId(authorizeRoleReqDto.getRoleId());
                            rrDto.setMerchantId(authorizeRoleReqDto.getMerchantId());
                            rrDto.setResourcesCode(resourcesCode);
                            rrDto.setCreateUserId(Long.valueOf(authorizeRoleReqDto.getUserId()));
                            rrDto.setCreateTime(Calendar.getInstance().getTime());
                            rrDto.setDelFlag("0");
                            list.add(rrDto);
                        }
                    }
                }
            }
            if(CollectionUtils.isNotEmpty(list)){
                roleResourcesMapper.batchAdd(list);
            }
        }

        // 清除角色权限
        // roleResourcesKey: 只针对案场助手的 getOptAuth 方法
        String roleResourcesKey = RedisKeyConstant.RoleResources.RESOURCES_GETOPTAUTH_ROLEID_ + authorizeRoleReqDto.getRoleId();
        RedisUtil.delete(roleResourcesKey);

        resDto.setResult(ResultEnum.SUCCESS.getNo());
        resDto.setResultMsg("角色授权成功");
        return resDto;
    }

    @Override
    public GetAuthorizeRoleListResDto getAuthorizeRoleListForDeveloper(GetAuthorizeRoleListReqDto getAuthorizeRoleListReqDto) throws Exception{
        GetAuthorizeRoleListResDto resDto = new GetAuthorizeRoleListResDto();

        // 查询所有功能权限
        UserResourcesDto userResourcesDto = new UserResourcesDto();
        String loginType = getAuthorizeRoleListReqDto.getLoginType();
        
        Long time1 = System.currentTimeMillis();
        
        //判断请求来自手机端还是PC端   此处以前的业务逻辑为 ResourcesTypeEnum.PC  写死获取PC端
        if (SystemIdEnum.AGENCY_h5.getCode().equals(loginType) ||SystemIdEnum.WEAPP_AGENCY.getCode().equals(loginType) || SystemIdEnum.ASSISTANT.getCode().equals(loginType)
                || SystemIdEnum.APP_ASSISTANT.getCode().equals(loginType) || SystemIdEnum.APP_AGENCY.getCode().equals(loginType)) {
            userResourcesDto.setResourcesType(ResourcesTypeEnum.APP.getNo());
        }else if (SystemIdEnum.AGENCY_WEB.getCode().equals(loginType)) {
            userResourcesDto.setResourcesType(ResourcesTypeEnum.PC.getNo());
        }
        
        //此处以前的业务逻辑是ResourcesOriginEnum.CHANNEL 写死为分销商
        userResourcesDto.setResourcesOrigin(getAuthorizeRoleListReqDto.getResourcesOrigin());
        userResourcesDto.setOrders(" t2.resources_code,t2.resources_sort ");
        List<Resources> responseList = resourcesService.findUserResources(userResourcesDto);
        
        Long time2 = System.currentTimeMillis();
        log.info("RoleResourcesService-->getAuthorizeRoleListForDeveloper-->查询全部资源耗时: {}", (time2 - time1));

        //查询该角色已被授权的权限
        RoleResourcesDto roleResourcesDto = new RoleResourcesDto();
        roleResourcesDto.setRoleId(getAuthorizeRoleListReqDto.getRoleId());
        List<RoleResources> authorizedList = roleResourcesMapper.selectListByDto(roleResourcesDto);
        //查询复用前的角色  未做去重处理，因为前端只是用于展示，保存会重新查询
        if (getAuthorizeRoleListReqDto.getOldRoleId() != null){
            roleResourcesDto.setRoleId(getAuthorizeRoleListReqDto.getOldRoleId());
            List<RoleResources> oldAuthorizedList = roleResourcesMapper.selectListByDto(roleResourcesDto);
            authorizedList.addAll(oldAuthorizedList);
        }

        Long time3 = System.currentTimeMillis();
        log.info("RoleResourcesService-->getAuthorizeRoleListForDeveloper-->查询角色已被授权权限: {}", (time3 - time2));
        
        Map<String,ZNodes> mapZnode = new HashMap<>();
        List<ZNodes> webList = new ArrayList<>();
        List<ZNodes> h5List = new ArrayList<>();
        //整理节点
        for(Resources r : responseList){
            ZNodes znode = new ZNodes();
            znode.setId(r.getResourcesCode());
            znode.setpId(r.getParentCode());
            znode.setName(r.getResourcesName());
            znode.setChkDisabled("false");
            znode.setSubNodes(new ArrayList<>());
            znode.setShow(true);
            znode.setSelected(false);
            boolean flag = false;
            if (authorizedList != null && authorizedList.size() > 0) {
                for (RoleResources rr : authorizedList) {
                    if (r.getResourcesCode().equals(rr.getResourcesCode())) {
                        flag = true;
                        break;
                    }
                }
                znode.setChecked(String.valueOf(flag));
                znode.setSelected(flag);
            }
            if(mapZnode.containsKey(r.getParentCode())){
                mapZnode.get(r.getParentCode()).getSubNodes().add(znode);
            }else{
                //区分，H5
                if(ResourcesTypeEnum.PC.getNo().equals(r.getResourcesType()) ){
                    webList.add(znode);
                }else if(ResourcesTypeEnum.APP.getNo().equals(r.getResourcesType())){
                    h5List.add(znode);
                }
            }
            mapZnode.put(r.getResourcesCode(),znode);
        }
        
        Long time4 = System.currentTimeMillis();
        log.info("RoleResourcesService-->getAuthorizeRoleListForDeveloper-->循环拼接节点时间: {}", (time4 - time3));
        
        
        //报备数据权限
        RoleCaseMemberDto roleCaseMemberDto = roleCaseMemberService.listRoleCaseMember(getAuthorizeRoleListReqDto.getRoleId(), getAuthorizeRoleListReqDto.getMerchantId());

        
        Long time5 = System.currentTimeMillis();
        log.info("RoleResourcesService-->getAuthorizeRoleListForDeveloper-->报备数据权限: {}", (time5 - time4));
        
        resDto.setNodeList(webList);
        resDto.setH5List(h5List);
        resDto.setRoleCaseMemberDto(roleCaseMemberDto);
        resDto.setResult(ResultEnum.SUCCESS.getNo());
        return resDto;
    }

    @Override
    public List<RoleResources> listRoleResources(Long roleId, List<String> resourcesCodes) {
        return roleResourcesMapper.listRoleResources(roleId,resourcesCodes);
    }
    
    /**
     * 将待确认权限刷入到报备待审和到访待审中
     *	本方法为一次性方法，将角色下所有的某一个菜单刷新至另外的菜单集合
     *	如果有业务需要，只需要更改
     *	resourcesCoe  需要改变的集合的值
     *
     *@param companyId 只要有值，则代表使用测试数据，生产环境使用的是巧房创研测试的公司ID
     *	
     */
    @Override
    @Transactional
    public void refreshVisitAuthority(String companyId) {
    	
    	List<Map<String, Object>> convertList = buildConvertList();
    	//使用遍历的方式，便于记录
    	for (Map<String, Object> map : convertList) {
			String resourcesCoe = (String) map.get("resourcesCoe");
			String[] toBeResourceCodes = (String[]) map.get("toBeResourceCodes");
			log.info("RoleResourcesServiceImpl->refreshVisitAuthority->本次转换数据为:{}", map);
			
			//1、查询已设置权限的行
			RoleResourcesDto roleResourcesDto = new RoleResourcesDto();
	    	roleResourcesDto.setResourcesCode(resourcesCoe);
	    	if(StringUtils.isNotBlank(companyId)) {
	    		roleResourcesDto.setMerchantId(Long.valueOf(companyId));
	    	}
	    	List<RoleResources> roleResourcesList = roleResourcesMapper.selectListByDto(roleResourcesDto);
	    	log.info("RoleResourcesServiceImpl->refreshVisitAuthority->查询权限相关数据共：{}条", roleResourcesList.size());
	    	log.info("RoleResourcesServiceImpl->refreshVisitAuthority->查询权限相关数据为：{}", roleResourcesList);
	    	List<String> hasDealed = new ArrayList<>();
	    	//2、组装数据并插入
	    	List<RoleResourcesDto> insertRoleResourcesList = new ArrayList<>();
	    	for (RoleResources roleResources : roleResourcesList) {
	    		if(hasDealed.contains(roleResources.getResourcesCode())) {
	    			continue;
	    		}
	    		hasDealed.add(roleResourcesDto.getResourcesCode());
	    		for (String toBeResourceCode : toBeResourceCodes) {
	    			RoleResourcesDto insertRoleResources = new RoleResourcesDto();
	    			BeanUtils.copyProperties(roleResources, insertRoleResources);
	    			insertRoleResources.setId(null);
	    			insertRoleResources.setResourcesCode(toBeResourceCode);
	    			insertRoleResources.setCreateTime(new Date());
	    			insertRoleResources.setUpdateTime(new Date());
	    			insertRoleResourcesList.add(insertRoleResources);
				}
			}
	    	if(CollectionUtils.isNotEmpty(insertRoleResourcesList)) {
	    		roleResourcesMapper.batchAdd(insertRoleResourcesList);
	    	}
	    	
	    	log.info("RoleResourcesServiceImpl->refreshVisitAuthority->插入权限相关数据共：{}条", insertRoleResourcesList.size());
	    	log.info("RoleResourcesServiceImpl->refreshVisitAuthority->插入权限相关数据：{}", insertRoleResourcesList);
	    	
	    	//3、删除所有数据
	    	if(CollectionUtils.isNotEmpty(roleResourcesList)) {
	    		int dels = roleResourcesMapper.dels(roleResourcesList);
	    		log.info("RoleResourcesServiceImpl->共删除{}条数据", dels);
	    	}else {
	    		log.info("RoleResourcesServiceImpl->共删除0条数据");
	    	}
		}
    	
    }
    
    private List<Map<String, Object>> buildConvertList(){
    	List<Map<String, Object>> convertList = new ArrayList<>();
    	
    	String resourcesCoe = "menu_0008_0001";
    	String[] toBeResourceCodes = new String[] {"menu_0008_0000", "menu_0008_0001"};
    	convertList.add(buildConvertMap(resourcesCoe, toBeResourceCodes));
    	
    	String resourcesCoe1 = "menu_0008_0001_0001";
    	String[] toBeResourceCodes1 = new String[] {"menu_0008_0000_0001"};
    	convertList.add(buildConvertMap(resourcesCoe1, toBeResourceCodes1));
    	
    	String resourcesCoe2 = "menu_0008_0001_0002";
    	String[] toBeResourceCodes2 = new String[] {"menu_0008_0001_0001"};
    	convertList.add(buildConvertMap(resourcesCoe2, toBeResourceCodes2));
    	
    	// 号码补全和报备无效存在历史bug问题，在此修复
    	String resourcesCoe3 = "menu_0008_0001_0003";
    	String[] toBeResourceCodes3 = new String[] {"menu_0008_0000_0003", "menu_0008_0001_0003", "menu_0008_0000_0002"};
    	convertList.add(buildConvertMap(resourcesCoe3, toBeResourceCodes3));
    	
    	String resourcesCoe5 = "menu_0008_0001_0004";
    	String[] toBeResourceCodes5 = new String[] {"menu_0008_0001_0002"};
    	convertList.add(buildConvertMap(resourcesCoe5, toBeResourceCodes5));
    	
    	return convertList;
    }
    
    private Map<String, Object> buildConvertMap(String resourcesCoe, String[] toBeResourceCodes) {
    	Map<String, Object> convertMap = new HashMap<>();
    	convertMap.put("resourcesCoe", resourcesCoe);
    	convertMap.put("toBeResourceCodes", toBeResourceCodes);
    	return convertMap;
    }
}
